/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.thienloc.omap.session;

import com.thienloc.omap.entity.OmapResource;
import com.thienloc.omap.entity.OmapRole;
import com.thienloc.omap.entity.OmapUser;
import com.thienloc.omap.entity.Permission;
import com.thienloc.omap.util.JsfUtil;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author GiangLT
 */
@Stateless
public class PermissionFacade extends AbstractFacade<Permission> {

    private final Logger logger = LoggerFactory.getLogger(PermissionFacade.class);
    @PersistenceContext(unitName = "omapPU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public PermissionFacade() {
        super(Permission.class);
    }

    public void createPermissionSet(OmapResource resource) throws Exception {
        List<Permission> list = new ArrayList<Permission>(4);
        Permission permission = new Permission();
        permission.setResourceId(resource);
        permission.setAction("view");
        list.add(permission);

        permission = new Permission();
        permission.setResourceId(resource);
        permission.setAction("add");
        list.add(permission);

        permission = new Permission();
        permission.setResourceId(resource);
        permission.setAction("update");
        list.add(permission);

        permission = new Permission();
        permission.setResourceId(resource);
        permission.setAction("delete");
        list.add(permission);

        batchCreate(list);
        logger.debug("Created CRUD permissions for resource {} (id = {})", resource.getName(), resource.getId());
    }

    public List<Permission> findByUserId(Integer userId) {
        try {
            String sql = "SELECT p.id FROM permission p "
                    + " INNER JOIN user_permission up ON p.id = up.permission_id "
                    + " INNER JOIN omap_user u on u.user_id = up.user_id "
                    + " WHERE u.user_id = " + userId;
            Query q = em.createNativeQuery(sql);

            List rows = q.getResultList();

            List<Permission> result = new ArrayList<Permission>();
            for (Object row : rows) {
                Permission permission = find((BigDecimal) row);
                result.add(permission);
            }
            return result;
        } catch (NoResultException ex) {
            return null;
        } catch (Exception ex) {
            logger.error("", ex);
            return null;
        }
    }

    public List<Permission> findByRoleId(Integer roleId) {
        try {
            String sql = "SELECT p.id FROM permission p "
                    + " INNER JOIN role_permission up ON p.id = up.permission_id "
                    + " INNER JOIN omap_role u on u.role_id = up.role_id "
                    + " WHERE u.role_id = " + roleId;
            Query q = em.createNativeQuery(sql);

            List rows = q.getResultList();

            List<Permission> result = new ArrayList<Permission>();
            for (Object row : rows) {
                Permission permission = find((BigDecimal) row);
                result.add(permission);
            }
            return result;
        } catch (NoResultException ex) {
            return null;
        } catch (Exception ex) {
            logger.error("", ex);
            return null;
        }
    }

    public List<Permission> findByResourceId(Integer resourceId) {
        try {
            TypedQuery<Permission> q = em.createNamedQuery("Permission.findByResourceId", Permission.class);
            q.setParameter("resourceId", BigDecimal.valueOf(resourceId));
            List<Permission> result = q.getResultList();
            return result;
        } catch (NoResultException ex) {
            return null;
        } catch (Exception ex) {
            logger.error("", ex);
            return null;
        }
    }

    @Override
    public void edit(Permission entity) throws Exception {
        super.edit(entity);
        
        Query q = em.createNativeQuery("DELETE FROM user_permission WHERE permission_id = " + entity.getId());
        q.executeUpdate();
        for (OmapUser user : entity.getOmapUserList()) {
            try {
                q = em.createNativeQuery("INSERT INTO user_permission (user_id, permission_id) values (" + user.getUserId() + ", " + entity.getId() + ")");
                q.executeUpdate();
            } catch (Exception ex) {
                logger.error("Cannot create relationship between user {} and permission {}", user.getUserId(), entity.getId());
                logger.error("", ex);
                JsfUtil.addErrorMessage("Lỗi cập nhật quyền", "Một số quyền người dùng không cập nhật được");
            }
        }

        q = em.createNativeQuery("DELETE FROM role_permission WHERE permission_id = " + entity.getId());
        q.executeUpdate();
        for (OmapRole role : entity.getOmapRoleList()) {
            try {
                q = em.createNativeQuery("INSERT INTO role_permission (role_id, permission_id) values (" + role.getRoleId() + ", " + entity.getId() + ")");
                q.executeUpdate();
            } catch (Exception ex) {
                logger.error("Cannot create relationship between role {} and permission {}", role.getRoleId(), entity.getId());
                logger.error("", ex);
                JsfUtil.addErrorMessage("Lỗi cập nhật quyền", "Một số quyền của nhóm không cập nhật được");
            }
        }
    }
}
